<?php

namespace App\ServicesNew\Impl;

use App\Entities\GoodsPaymentModel;
use App\Entities\OrderEntity;
use App\Entities\OrderModel;
use App\Entities\OrderRefundEntity;
use App\Entities\PaymentEntity;
use App\Entities\PaymentModel;
use App\ServicesNew\BaseSearchServiceTrait;
use App\ServicesNew\OrderService;
use App\VO\UserOrder\MetaInfo\UserOrderSearchInfo;
use Illuminate\Support\Facades\DB;

class OrderServiceImpl implements OrderService
{
    use BaseSearchServiceTrait;

    /**
     * 缓存
     * @var array
     */
    protected static $orderCacheById = [];

    /**
     * @param OrderEntity $orderEntity
     */
    protected function cacheOrderById(OrderEntity $orderEntity)
    {
        self::$orderCacheById[$orderEntity->getId()] = $orderEntity;
    }

    /**
     * 从缓存获取
     * @param int $orderId
     * @return OrderEntity|null
     */
    protected function getOrderFromCache(int $orderId)
    {
        return self::$orderCacheById[$orderId] ?? null;
    }

    /**
     * @inheritDoc
     */
    public function findOrderEntityById(int $orderId)
    {
        $orderEntity = $this->getOrderFromCache($orderId);
        if ($orderEntity instanceof OrderEntity) {
            return $orderEntity;
        }

        $orderEntity = OrderEntity::find($orderId);
        if ($orderEntity instanceof OrderEntity) {
            $this->cacheOrderById($orderEntity);
        }

        return $orderEntity;
    }

    /**
     * @inheritDoc
     */
    public function findOrderEntityByIdAndUserId(int $orderId, int $userId)
    {
        $orderEntity = $this->findOrderEntityById($orderId);
        if (is_null($orderEntity)) {
            return null;
        }

        if ($userId != $orderEntity->getUserId()) {
            return null;
        }

        return $orderEntity;
    }

    /**
     * @inheritDoc
     */
    public function getOrderEntities(UserOrderSearchInfo $searchInfo)
    {
        return $this->getEntities(OrderEntity::class, OrderModel::class, $searchInfo);
    }

    /**
     * @inheritDoc
     */
    public function count(UserOrderSearchInfo $searchInfo)
    {
        return $this->countNum(OrderModel::class, $searchInfo);
    }

    private function getSearchCondition(UserOrderSearchInfo $searchInfo)
    {
        $condition = [];
        $userId = $searchInfo->getUserId();
        if ($userId > 0) {
            $condition[] = ['user_id', $userId];
        }

        $orderStates = $searchInfo->getOrderStates();
        if (!empty($orderStates)) {
            $str = sprintf('order_state in (%s)', implode(',', $orderStates));
            $condition[] = [DB::raw($str), 1];
        }
        return $condition;
    }

    /**
     * @inheritDoc
     */
    public function getOrderPeriodCount(int $cityId, int $productId, string $day, string $timePeriodId)
    {
        // 获取库存限制
        $refund_status = OrderModel::REFUND_STATUS_SUCCESS;
        $ship_status = OrderModel::SHIP_STATUS_DELIVERED;
        $orders_closed = OrderModel::ORDER_CLOSED;

        $sql = "SELECT count(1) as total
                    FROM orders
                    LEFT JOIN order_items ON orders.id = order_items.order_id
                    WHERE orders.city_id = {$cityId}
                    AND orders.assignDate = '{$day}'
                    AND orders.assignTime = {$timePeriodId}
                    AND orders.closed != {$orders_closed}
                    AND orders.refund_status != '{$refund_status}'
                    AND orders.ship_status != '{$ship_status}'
                    AND order_items.product_id = {$productId}
            ";
        $ret = DB::select($sql);
        return $ret[0]->total;
    }

    /**
     * @inheritDoc
     */
    public function getSupplementPaymentsByOrderId(int $orderId, bool $includeMasterGoods = false)
    {
        $goodsPayments = GoodsPaymentModel::where('order_id', $orderId)->get();
        $payments = PaymentModel::whereIn('trade_no', array_column($goodsPayments->toArray(), 'trade_no'))->get();

        $tmp = [];
        foreach ($payments as $payment) {
            $tmp[] = new PaymentEntity($payment);
        }
        return $tmp;
    }

    /**
     * @inheritDoc
     */
    public function findOrderRefundOneByOrderId(int $orderId)
    {
        return OrderRefundEntity::findByOrderId($orderId);
    }
}
